/*
  provide/inject原理
    provide 就是给当前组件添加了额一个私有属性 _provided

    inject 的处理就是利用while循环一层一层的向上查找_provided属性

  extend原理 扩展一个Vue的子类
    利用原型继承 创造一个Vue的子类

  nextTick(cb) cb会在下一次渲染完成之后触发
    DOM 的更新是一个异步操作  
    原理就是一个发布订阅+异步实现


  双向数据绑定原理
  
    通过Observe大类去进行数据劫持的时候 给每一个被劫持的属性都赋予了一个
      dep实例(new Dep) dep实例有一个subs属性，对应的是一个数组
      这个数组中存储的都是一个使用当前属性时创造的Watcher
      这些watcher实例啥时候放入的?是当触发对应户型的get函数的存进去的
      （每当有地方使用这个属性 的时候 就会触发这个属性的get方法，同时会创建一个
      观察者watcher实例，创造完成之后 就会触发这个watcher的addDep方法，从而调用dep实例的
      addSub方法，然后就会当前watcher存入到了dep的subs数组中了）

      当被劫持的那个数据更新的时候 会触发这个属性的set函数，
        set函数执行的时候 会触发自己的dep实例的notify方法
        notify执行 循环了dep的subs数组，让数组中的每一个watcher实例
        执行update方法， 从而更新视图

  $set原理
  数组的七个变异方法原理  原型Vue数组的原型重写     
  
  computed原理
    计算属性 可以理解成一个惰性watcher 依赖watcher的一个dirty属性

    我们在调用某个计算属性的时候 会触发这个属性的get函数
    这个属性的get函数对应的就是createComputedGetter的返回结果
      就是一个computedGetter函数
      也就是说 我们在使用计算属性的时候 获取到的其实是computedGetter函数
      的返回结果  这个函数的返回结果时改计算属性对应的那个watcher的value值

    初始使用该计算属性的时候 会调用用户定义的那个get函数，这个使用的那些vue变量
    会触发这个属性的依赖收集，收集的时候就会把当前计算属性对应的watcher收集到
    这些vue变量的subs中  当这些vue变量更新的时候 就会触发他自己所有的watcher执行
    update,执行update的时候就会把dirty属性改成true
    这样的化 当模板重新调用这个计算属性的时候 
    就会触发计算属性对应的watcher evaluate方法
    这个方法一执行 就会更新 当前watcher的value

    reName(){return this.name}  // dep subs[watcher]


  侦听器watch的原理  就是给被侦听的那个属性在添加一个watcher实例
  当这个属性更新的时候 就会触发该watcher的update 
  update执行的时候会触发这个watcher的run方法 run一执行 就会让对应的
  handler执行并且把新值和旧值都传给handler函数 

  Vue use mixin 原理

  keep-alive原理

*/


import Vue from 'vue'
import App from './App'
Vue.filter('mm', function (val) {
  return (val + '').replace(/\d(?=(\d{3})+$)/g, '$&,') + '.00';
})
let obj = {
  name: 'qqqq',
  data() {
    return {
      a: 123
    }
  },
}
// let SUB1 = Vue.extend(obj)
// let SUB2 = Vue.extend(obj)
// console.log(Vue.extend)
// console.log(SUB1 == SUB2)

Vue.mixin({
  data() {
    return {
      qqq: 666
    }
  },
  created() {
    console.log('这是混入的created执行了', this.qqq, this.type)
  }
})

Vue.use(function (Vue, ...options) {
  console.log(arguments)
}, 1, 2, 3, 4, 5)

Vue.use({
  install(Vue, ...options) {
    console.log(arguments, this)

  },
  qqq: 123,
  rrr: 555
}, 1111, 2222)
let vm = new Vue({

  render(h) {
    return h(App)
  },
  data() {
    return {
      type: 111
    }
  }

}).$mount('#app')
// console.dir(Vue)

/*
  混入 记住一个原则就是以组件数据为准
      data中的属性重复 以组件的data为准
      钩子函数重复 混入的先执行，组件自己的后执行
  Vue.mixin 全局混入
  mixins  局部混入





*/